package com.zdy.socketserver.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URI;
import java.util.concurrent.TimeUnit;

/**
 * @author myh
 * @date 2024/6/11
 */
@Slf4j
@Component
public class NettyClient {
    Bootstrap bootstrap = null;

    int failedCount = 1;

    @Value("${netty.host}")
    private String host;
    @Value("${netty.port}")
    private Integer port;


    public void initClient(){

        EventLoopGroup group = new NioEventLoopGroup();
        bootstrap = new Bootstrap();
        //设置相关组件
        bootstrap.group(group)
                .channel(NioSocketChannel.class)//通过TCP/IP方式进行传输
                .option(ChannelOption.SO_KEEPALIVE, true)
                .handler(new ChannelInitializer<Channel>() {
                    @Override
                    protected void initChannel(Channel channel) throws Exception {
                        // 添加HTTP编解码器（WebSocket是基于HTTP的）
                        channel.pipeline().addLast(new HttpClientCodec());
                        // 聚合HTTP消息到FullHttpRequest或FullHttpResponse
                        channel.pipeline().addLast(new HttpObjectAggregator(8192));

                        // 添加WebSocket协议处理器
                        URI uri = new URI("ws://"+host+":"+port+"/socket");
                        WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker(
                                uri, WebSocketVersion.V13, null, false, new DefaultHttpHeaders());
                        channel.pipeline().addLast( new WebSocketClientProtocolHandler(handshaker));

                        //channel.pipeline().addLast(new NettyMsgDecoder());//自定义解码器
                        //channel.pipeline().addLast(new NettyMsgEncoder());//自定义编码器
                        //channel.pipeline().addLast(new IdleStateHandler(0, 180, 0, TimeUnit.SECONDS));
                        channel.pipeline().addLast(new MyWebSocketClientHandler(NettyClient.this));
                    }
                });
        try {
            connect();
        } catch (InterruptedException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }


    }

    public void connect() throws InterruptedException {
        ChannelFuture channelFuture = bootstrap.connect(host, port);
        channelFuture.addListener((ChannelFutureListener) future -> {
            if (channelFuture.isSuccess()) {
                log.info("连接成功，服务端地址{}",host+":"+port);
                failedCount = 1;
            } else {
                log.info("第"+failedCount+"次重新连接");
                channelFuture.channel().eventLoop().schedule(() -> {
                    log.info("连接失败");
                    try {
                        failedCount++;
                        connect();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }, 3, TimeUnit.SECONDS);
            }
        });
        //给关闭通道进行监听
        channelFuture.channel().closeFuture().sync();
    }

    /**
     * 获取电脑mac地址
     * @return
     * @throws Exception
     */
    public static String getMACAddress() throws Exception {
        InetAddress ia = InetAddress.getLocalHost();// 获取本地IP对象
        // 获得网络接口对象（即网卡），并得到mac地址，mac地址存在于一个byte数组中。
        byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
        // 下面代码是把mac地址拼装成String
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < mac.length; i++) {
            if (i != 0) {
                sb.append(":");
            }
            // mac[i] & 0xFF 是为了把byte转化为正整数
            String s = Integer.toHexString(mac[i] & 0xFF);
            // System.out.println("--------------");
            // System.err.println(s);
            sb.append(s.length() == 1 ? 0 + s : s);
        }
        // 把字符串所有小写字母改为大写成为正规的mac地址并返回
        return sb.toString().toUpperCase();
    }



}
